from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash

from flask.json import jsonify

from info import redis_store, constants, db
from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.utils.captcha.captcha import captcha as capt
from info.utils import response_code
from . import passport_blu
import random
import re

from flask import request, abort, current_app, make_response, session


@passport_blu.route("/logout")
def logout():

    """
    退出denglu
    :return:
    """
    # 移出session中的数据,None pop有一个返回值，没有就返回None
    session.pop("user_id",None)
    session.pop("mobile",None)
    session.pop("nick_name",None)

    return jsonify(errorn = response_code.RET.OK,errmsg = "退出成功")


@passport_blu.route("/login",methods = ["POST"])
def login():
    """
    1.获取参数
    2.校验参数
    3.校验密码
    4.登录状态
    5.返回响应
    :return:
    """
    params_dic = request.json

    mobile = params_dic.get("mobile")
    passport = params_dic.get("passport")

    # 判断是否有收到参数
    if not all([passport,mobile]):

        return jsonify(errorn =response_code.RET.PARAMERR,errmsg = "参数错误")
    # 判断是否有当前手机号
    if not re.match("1[37865]\\d{9}$",mobile):

        return jsonify(errorn =response_code.RET.PARAMERR,errmsg = "手机号码不正确" )

    # 查询是否有当前用户
    try:
        user = User.query.filter(User.mobile == mobile).first()

    except Exception as e:

        current_app.logger.error(e)

        return jsonify(errorn =response_code.RET.DATAERR,errmsg = "数据查询错误" )

    # 校验登录的密码与当前用户的密码是否一致.;;.//////////////......;/;.;;;;;;;;;;;;;;;;;99999999999999999999999999999999

    if not user:
        return jsonify(errorn =response_code.RET.NODATA,errmsg = "用户不存在" )

    # 校验用户密码与当前密码是否一致

    if not user.check_passowrd(passport):

        return jsonify(errorn =response_code.RET.PWDERR,errmsg = "用户名或者密码错误" )

        # 往session中保存数据
    session["user_id"] = user.id
    session["mobile"] = user.mobile
    session["nick_name"] = user.nick_name

    # 如果在视图函数中，对模型身上的属性有修改，那么需要commit到数据库
    # 但是其实可以不用自己写 db.session.commit(),前提是对SQLALchemy有过相关设置

    # 记录最后一次登录时间
    user.last_login = datetime.now()

    try:
        db.session.commit()

    except Exception as e:

        db.session.rollack()
        current_app.logger.error(e)



    # 响应

    return jsonify(errorn = response_code.RET.OK ,errmsg = "登录成功")

@passport_blu.route("/register",methods = ["POST"])
def register():


    # 获取参数
    parmas_dict = request.json

    mobile = parmas_dict.get("mobile")
    smscode = parmas_dict.get("smscode")
    password = parmas_dict.get("password")



    # 校验参数

    if not all([mobile,smscode,password]):

        return jsonify(errorn =response_code.RET.PARAMERR,errmsg = "参数不全")
    if not re.match("1[37865]\\d{9}$",mobile):

        return jsonify(errorn =response_code.RET.PARAMERR,errmsg = "手机号码不正确" )

    # 取到服务器保存的真实的短信验证码内容
    try:
        mess = redis_store.get("SMS_" + mobile)

    except Exception as e :

        current_app.logger.error(e)

        return jsonify(errorn =response_code.RET.DBERR,errmsg = "数据查询失败" )

    if not mess:

        return jsonify(errorn =response_code.RET.DATAERR,errmsg = "图片验证码已过期" )


    # 校验用户输入的短信验证码内容和真实验证码的内容是否一致

    if mess != smscode:
        return jsonify(errorn =response_code.RET.DATAERR,errmsg = "验证码输入错误" )

    # 如果一致初始化User模型，并且赋值属性
    user = User()
    user.mobile = mobile
    user.nick_name = mobile

    # 记录用户最后一次登录时间
    user.last_login = datetime.now()

    # TODO 密码加密处理
    # user.password = generate_password_hash(password)
    user.password = password

    # 添加到数据库
    try:

        db.session.add(user)
        db.session.commit()

    except Exception as e :

        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errorn =response_code.RET.DBERR,errmsg = "数据保存失败" )

    # 往session中保存数据
    session["user_id"] = user.id
    session["mobile"] = user.mobile
    session["nick_name"] = user.nick_name


    # 返回响应
    return jsonify(errorn = response_code.RET.OK,errmsg = "注册成功")













@passport_blu.route("sms_code",methods = ["POST"])
def send_sms_code():
    """
    1.拿到参数：用户手机号，验证码内容，图片验证码编号
    2.校验参数(参数是否符合规则，是否为空）
    3.从redis中取出验证码内容
    4.与用户验证码内容进行对比，如果不一致返回验证码错误
    5.如果一直生成验证码内容
    6.发送短信验证码
    7.告知发送结果
    :return:
    """




    params_dict = request.json

    mobile = params_dict.get("mobile")
    image_code = params_dict.get("image_Code")
    image_code_id = params_dict.get("image_CodeId")

    #2.校验参数(参数是否符合规则，是否为空）
    # 判断参数是否都值
    if mobile =="" or image_code == "" or image_code_id =="":

        return jsonify(errorn =response_code.RET.PARAMERR,errmsg = "参数有误" )
    # 校验手机号码是否正确
    if not re.match("1[37865]\\d{9}$",mobile):

        return jsonify(errorn =response_code.RET.PARAMERR,errmsg = "手机号码不正确" )
    try:

        rel_image_code = redis_store.get("ImageCodeId" + image_code_id)

    except Exception as e:

        current_app.logger.error(e)

        return jsonify(errorn =response_code.RET.DATAERR,errmsg = "数据查询失败" )

    if not rel_image_code:

        return jsonify(errorn =response_code.RET.NODATA,errmsg = "图片验证码已过期" )

    if rel_image_code.upper() != image_code.upper():

        return jsonify(errorn =response_code.RET.DATAERR,errmsg = "图片验证码已过期" )

    # 如果一直声称短信验证码
    # 随机数字保证是六位数字
    sms_code_str ="%6d" % random.randint(0,999999)

    print(sms_code_str)

    current_app.logger.debug("短信验证码内容是 %s"% sms_code_str)

    # 发送短信验证码
    # result = CCP().send_template_sms(mobile,[sms_code_str,constants.SMS_CODE_REDIS_EXPIRES / 5],"1")
    #
    # if result != 0:
    #     return jsonify(errorn =response_code.RET.THIRDERR,errmsg = "短信发送失败" )

    # 保存验证码到redis
    try:
        redis_store.set("SMS_"+ mobile,sms_code_str,constants.SMS_CODE_REDIS_EXPIRES)

    except Exception as e:

        current_app.logger.error(e)

        return jsonify(errorn =response_code.RET.DBERR,errmsg = "短信发送失败" )


    # 告知发送结果
    return jsonify(errorn = response_code.RET.OK,errmsg = "发送成功")















@passport_blu.route('/image_code')
def get_image_code():
    """
    生成图片验证码并返回
    1.取到参数
    2.判断参数是否有值
    3.生成图片验证码
    4.保存图片验证码的文字内容到redis
    5.返回验证码图片
    ：return；


    :return:
    """
    #1取到参数
    # args:取到url中？后面的采纳数
    image_code_id = request.args.get("imageCodeId",None)
    # 2.
    # 判断参数是否有值
    if not image_code_id:
        return abort(403)
    # 3.
    # 生成图片验证码
    name,text,image = capt.generate_captcha()
    current_app.logger.debug("图片验证码内容是 %s" %text)
    # 4.
    # 保存图片验证码的文字内容到redis
    try:
        redis_store.set("ImageCodeId" + image_code_id,text,constants.IMAGE_CODE_REDIS_EXPIRES)

    except Exception as e:
        current_app.logger.error(e)

        abort(500)
    # 5.
    # 返回验证码图片
    response = make_response(image)
    response.headers['Content-Type'] = "image/jpg"
    return response 